import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormArray, FormBuilder, AbstractControl } from '@angular/forms';
import { FilterGroupOperate } from '../../proxy/joy/erp/basic-archives/core/filters/filter-group-operate.enum';
import { FilterRuleOperate } from '../../proxy/joy/erp/basic-archives/core/filters/filter-rule-operate.enum';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';

@Component({
  selector: 'filter-group',
  template: `
    <div [formGroup]="group">
      <nz-card>
        <div class="card-title">
          <div class="title-buttons">
            <button nz-button (click)="addRule()">{{ 'BasicArchives::UI:AdvancedFilterDialog.Button.AddRule' | abpLocalization }}</button>
            <button nz-button (click)="addGroup()">{{ 'BasicArchives::UI:AdvancedFilterDialog.Button.AddGroup' | abpLocalization }}</button>
          </div>
        </div>
        <div class="filter-group">
          <!-- Rules -->
          <div formArrayName="rules" class="rules-container">
            <div *ngFor="let rule of rules.controls; let i=index" class="rule-container">
              <div *ngIf="i > 0" class="operate-label" (click)="toggleOperate()">
                {{ 'BasicArchives::UI:AdvancedFilterDialog.GroupOperateOptions.' + FilterGroupOperate[group.get('operate').value] | abpLocalization }}
              </div>
              
              <div [formGroupName]="i" class="filter-rule">
                <nz-select formControlName="field" style="width: 150px;" [placeholder]="'BasicArchives::UI:AdvancedFilterDialog.ModelTitle.PlaceHolder.Property' | abpLocalization">
                  <nz-option 
                    *ngFor="let prop of entityConfig?.propertys" 
                    [nzValue]="prop.name"
                    [nzLabel]="'BasicArchives::ModelTitle:' + entityConfig?.entityType + '.' + prop.name | abpLocalization">
                  </nz-option>
                </nz-select>
                <nz-select formControlName="operate" style="width: 120px;">
                  <nz-option *ngFor="let op of getOperateOptions(getSelectedPropertyType(i))" 
                    [nzValue]="op.value" 
                    [nzLabel]="'BasicArchives::UI:AdvancedFilterDialog.OperateOptions.' + op.label | abpLocalization">
                  </nz-option>
                </nz-select>

                <!-- 根据属性类型显示不同的输入控件 -->
                <ng-container [ngSwitch]="getSelectedPropertyType(i)">
                  <!-- 日期类型 -->
                  <nz-date-picker
                    *ngSwitchCase="'date'"
                    formControlName="value"
                    [nzFormat]="'yyyy-MM-dd'"
                    style="width: 150px;"
                    (keydown.enter)="onEnterKeyPress($event)">
                  </nz-date-picker>

                  <!-- 数字类型 -->
                  <nz-input-number
                    *ngSwitchCase="'number'"
                    formControlName="value"
                    [nzMin]="0"
                    style="width: 150px;"
                    (keydown.enter)="onEnterKeyPress($event)">
                  </nz-input-number>

                  <!-- 默认文本类型 -->
                  <input
                    *ngSwitchDefault
                    nz-input
                    formControlName="value"
                    [placeholder]="'BasicArchives::UI:AdvancedFilterDialog.ModelTitle.PlaceHolder.Value' | abpLocalization"
                    style="width: 150px;"
                    (keydown.enter)="onEnterKeyPress($event)">

                </ng-container>

                <button nz-button nzType="link" (click)="removeRule(i)">
                  <i nz-icon nzType="delete" nzTheme="outline"></i>
                </button>
              </div>
            </div>
          </div>

          <!-- Nested Groups -->
          <div formArrayName="groups" class="groups-container">
            <div *ngFor="let nestedGroup of groups.controls; let i=index" class="rule-container">
              <div *ngIf="i > 0 || rules.length > 0" class="operate-label" (click)="toggleOperate()">
                {{ FilterGroupOperate[group.get('operate').value] }}
              </div>
              
              <div class="group-row">
                <div class="group-content">
                  <filter-group [group]="nestedGroup" [entityConfig]="entityConfig" (enterKeyPressed)="enterKeyPressed.emit()"></filter-group>
                </div>
                <div class="delete-button">
                  <button nz-button nzType="link" (click)="removeGroup(i)">
                    <i nz-icon nzType="delete" nzTheme="outline"></i>
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </nz-card>
    </div>
  `,
  styles: [`
    .card-title {
      margin-bottom: 16px;
    }

    .title-buttons {
      display: flex;
      gap: 8px;
    }

    .filter-group {
      margin-top: 16px;
    }

    .rules-container,
    .groups-container {
      margin-top: 8px;
    }

    .group-row {
      display: flex;
      align-items: flex-start;
      width: 100%;
    }

    .group-content {
      flex: 1;
      min-width: 0;
    }

    .delete-button {
      flex: none;
      padding-left: 8px;
    }
    
    .rule-container {
      margin-bottom: 12px;
    }

    .filter-rule {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .operate-label {
      display: inline-block;
      margin: 8px 0;
      padding: 4px 8px;
      background-color: #f0f0f0;
      border-radius: 4px;
      cursor: pointer;
      user-select: none;
      
      &:hover {
        background-color: #e0e0e0;
      }
    }
    
    :host ::ng-deep .ant-card {
      margin-bottom: 8px;
      width: 100%;
    }
  `]
})
export class FilterGroupComponent implements OnInit {
  @Input() group: FormGroup;
  @Input() entityConfig: any;
  @Output() enterKeyPressed = new EventEmitter<void>();
  FilterGroupOperate = FilterGroupOperate;
  FilterRuleOperate = FilterRuleOperate;

  filterRuleOperateOptions = Object.keys(FilterRuleOperate)
    .filter(key => !isNaN(Number(FilterRuleOperate[key])))
    .map(key => ({
      label: key,
      value: FilterRuleOperate[key]
    }));

  private operateOptionsCache = new Map<string, any[]>();

  constructor(private fb: FormBuilder) {}

  get rules() {
    return this.group.get('rules') as FormArray;
  }

  get groups() {
    return this.group.get('groups') as FormArray;
  }

  ngOnInit() {
    // 预先计算每种类型的操作选项并缓存
    ['string', 'date'].forEach(type => {
      this.operateOptionsCache.set(type, this.calculateOperateOptions(type));
    });
    
    // 默认操作选项缓存
    this.operateOptionsCache.set('default', this.filterRuleOperateOptions);
  }

  getOperateOptions(propertyType: string) {
    return this.operateOptionsCache.get(propertyType) || this.operateOptionsCache.get('default');
  }

  private calculateOperateOptions(propertyType: string) {
    const operateMap = {
      'date': [
        FilterRuleOperate.Equal,
        FilterRuleOperate.NotEqual,
        FilterRuleOperate.GreaterThan,
        FilterRuleOperate.GreaterThanOrEqual,
        FilterRuleOperate.LessThan,
        FilterRuleOperate.LessThanOrEqual,
        FilterRuleOperate.In
      ],
      'string': [
        FilterRuleOperate.Equal,
        FilterRuleOperate.NotEqual,
        FilterRuleOperate.StartsWith,
        FilterRuleOperate.EndsWith,
        FilterRuleOperate.In
      ]
    };

    const allowedOperates = operateMap[propertyType] || Object.values(FilterRuleOperate);
    
    return Object.keys(FilterRuleOperate)
      .filter(key => !isNaN(Number(FilterRuleOperate[key]))
        && allowedOperates.includes(FilterRuleOperate[key]))
      .map(key => ({
        label: key,
        value: FilterRuleOperate[key]
      }));
  }

  // 优化字段变化处理
  private setupFieldChangeListener(control: AbstractControl) {
    control.get('field').valueChanges
      .pipe(
        distinctUntilChanged(),
        debounceTime(100)
      )
      .subscribe(() => {
        // 只重置值，不重置字段
        control.patchValue({
          operate: FilterRuleOperate.Equal,
          value: null
        }, { emitEvent: false });
      });

    control.get('value').valueChanges
      .pipe(
        distinctUntilChanged(),
        debounceTime(100)
      )
      .subscribe(() => {
        this.formatDateValue(control);
      });
  }

  addRule() {
    const ruleForm = this.fb.group({
      field: [''],
      operate: [FilterRuleOperate.Equal],
      value: ['']
    });
    this.setupFieldChangeListener(ruleForm);
    this.rules.push(ruleForm);
  }

  removeRule(index: number) {
    this.rules.removeAt(index);
  }

  addGroup() {
    const groupForm = this.fb.group({
      operate: [FilterGroupOperate.And],
      rules: this.fb.array([]),
      groups: this.fb.array([])
    });
    this.groups.push(groupForm);
  }

  removeGroup(index: number) {
    this.groups.removeAt(index);
  }

  toggleOperate() {
    const currentOperate = this.group.get('operate').value;
    const newOperate = currentOperate === FilterGroupOperate.And ? 
      FilterGroupOperate.OrElse : FilterGroupOperate.And;
    this.group.patchValue({ operate: newOperate });
  }

  getSelectedPropertyType(index: number): string {
    const field = this.rules.at(index).get('field').value;
    const property = this.entityConfig?.propertys.find(p => p.name === field);
    
    // 根据属性类型返回对应的控件类型
    switch(property?.type?.toLowerCase()) {
      case 'date':
      case 'datetime':
        return 'date';
      case 'int':
      case 'int32':
      case 'int64':
      case 'long':
      case 'decimal':
      case 'double':
      case 'float':
        return 'number';
      default:
        return 'string';
    }
  }

  private formatDateValue(control: AbstractControl) {
    const field = control.get('field').value;
    const property = this.entityConfig?.propertys.find(p => p.name === field);
    
    if (property?.type?.toLowerCase() === 'date' || property?.type?.toLowerCase() === 'datetime') {
      const value = control.get('value').value;
      if (value) {
        const date = new Date(value);
        const formattedValue = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
        
        if (value !== formattedValue) {
          control.get('value').setValue(formattedValue, { emitEvent: false });
        }
      }
    }
  }

  onEnterKeyPress(event: KeyboardEvent) {
    event.preventDefault();
    event.stopPropagation();
    this.enterKeyPressed.emit();
  }
}